/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package conexao;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Vector;

/**
 *
 * @author UAB-2010
 */
public class Conexao_Cliente extends Thread {

  private String host;
  private int port;
  private Socket socket;
  private ObjectInputStream in;
  private ObjectOutputStream out;
  private boolean waitForMessage;

  public Conexao_Cliente(ServerSocket socket) {
    try {
      if (socket != null) {
        TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
                new ConectEvent("Esperando clientes...", ConectEvent.CONECTADO));
        this.socket = socket.accept();
        this.initStreams();
        
      } else {
        TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
                new ConectEvent("Servidor Fechado...", ConectEvent.CONECTADO));
      }
    } catch (IOException ex) {
    }

  }

  public Conexao_Cliente(String host, int port) {
    this.host = host;
    this.port = port;
    this.newSocket();
  }

  public void send(Object acao) {

    try {
      out.writeObject(acao);
      out.flush();
    } catch (IOException e) {
    }
  }

  public void disconnect() {
    this.waitForMessage = false;
  }

  // Executa tarefas em um novo sub-processo.
  @Override
  public void run() {
    if (socket != null) {
      this.receive();
    } else {
      TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
              new ConectEvent("Impossível Conectar...", ConectEvent.ERRO_CONEXAO));
    }

  }

  private void newSocket() {

    try {
      socket = new Socket(host, port);
      this.initStreams();
      
    } catch (IOException e) {
      TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
              new ConectEvent("Servidor Não Localizado...", ConectEvent.ERRO_CONEXAO));
      
    }
  }

  private void initStreams() {

    try {
      out = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
      out.flush();
      in = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));

      TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
              new ConectEvent("Conectado em:" + socket.getLocalSocketAddress(),
              ConectEvent.CONECTADO));
      
      TratadorConexao_Cliente.addConexao(this);
      
    } catch (IOException e) {
    }

  }

  private void receive() {

    // Define que a espera por mensagens esta ativa.
    this.waitForMessage = true;

    try {
      socket.setSoTimeout(3000);

    } catch (SocketException e) {
    }

    // Laco para espera de mensagens.
    while (waitForMessage) {
      try {
        
        TratadorConexao_Cliente.send(this, (Vector)in.readObject());

      } catch (SocketTimeoutException e) {
        continue;
      } catch (SocketException e) {

        break;
      } catch (EOFException e) {
        TratadorConexao_Cliente.getInstance().getSuporteEventos().disparaConectEvent(
                new ConectEvent("desconectou-se:" + socket.getLocalSocketAddress(),
                ConectEvent.CONECTADO));
        break;
      } catch (IOException ex) {
      } catch (ClassNotFoundException e) {
      }
    }
    this.closeConnection();
  }
  // Finaliza a conexao fechando os fluxos e o socket

  public void closeConnection() {

    try {
      in.close();
      out.close();
      socket.close();

    } catch (IOException e) {
    }
  }
}
